package com.xgq.drink.websocket;

import com.xgq.drink.utils.JwtTokenUtil;
import com.xgq.drink.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * WebSocket认证拦截器
 * 用于在WebSocket连接建立前验证用户身份，并将用户ID存入会话属性
 */
@Slf4j
@Component
public class WebSocketAuthenticationHandler implements HandshakeInterceptor {
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private RedisUtil redisUtil;
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, 
                                  WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        try {
            log.info("WebSocket握手开始，请求URI: {}", request.getURI());
            
            // 获取token
            String token = extractToken(request);
            log.info("提取的Token: {}", token);
            
            if (StringUtils.hasText(token)) {
                // 从token中获取用户ID
                String userIdStr = jwtTokenUtil.getUserIdFromToken(token);
                Long brandId = jwtTokenUtil.getStoreIdFromToken2(token);
                if (brandId != null) {
                    userIdStr = "1000"+brandId;
                }
                log.info("从Token中解析的用户ID: {}", userIdStr);
                
                if (userIdStr != null && !userIdStr.isEmpty()) {
                    try {
                        Long userId = Long.parseLong(userIdStr);

                        log.info("WebSocket认证成功，用户ID: {}", userId);
                        // 将用户ID存入会话属性
                        attributes.put("userId", userId);
                        return true;
                    } catch (NumberFormatException e) {
                        log.error("WebSocket认证失败，用户ID格式不正确: {}", userIdStr, e);
                    }
                } else {
                    log.warn("WebSocket认证失败，无法从token获取用户ID");
                }
            } else {
                log.warn("WebSocket认证失败，未提供token");
            }
            
            return false;
        } catch (Exception e) {
            log.error("WebSocket认证异常", e);
            return false;
        }
    }
    
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, 
                              WebSocketHandler wsHandler, Exception exception) {
        if (exception != null) {
            log.error("WebSocket握手后发生异常", exception);
        } else {
            try {
                String token = extractToken(request);
                String userId = jwtTokenUtil.getUserIdFromToken(token);
                if (userId != null) {
                    // 存储多维度在线状态
                    redisUtil.set("ws:online:" + userId, "connected", 600, TimeUnit.MINUTES);
                    redisUtil.hset("ws:connections", userId, LocalDateTime.now().toString());
                }
            } catch (Exception e) {
                log.error("Redis状态存储异常", e);
            }
            log.info("WebSocket握手完成");
        }
    }
    
    /**
     * 从请求中提取token
     */
    private String extractToken(ServerHttpRequest request) {
        log.info("开始从请求中提取token");
        if (request instanceof ServletServerHttpRequest) {
            // 尝试从URL参数中获取token
            ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request;
            String token = serverRequest.getServletRequest().getParameter("token");
            log.info("从URL参数中提取的token: {}", token);
            
            if (StringUtils.hasText(token)) {
                return token;
            }
            
            // 尝试从请求头中获取token
            HttpHeaders headers = request.getHeaders();
            List<String> authorization = headers.get("Authorization");
            log.info("Authorization请求头: {}", authorization);
            
            if (authorization != null && !authorization.isEmpty()) {
                String authHeader = authorization.get(0);
                if (StringUtils.hasText(authHeader) && authHeader.startsWith("Bearer ")) {
                    return authHeader.substring(7);
                }
            }
        }
        
        log.warn("未能从请求中提取到token");
        return null;
    }
} 